/*
 * pcm.h
 *
 *  Created on: 2022年8月29日
 *      Author: pengkun.he
 */
#ifndef SRC_PCM_PCM_H_
#define SRC_PCM_PCM_H_
#include <stdio.h>
#include <linux/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <termios.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <pthread.h>
#include <poll.h>
#include <signal.h>
#include <sys/mman.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <errno.h>
typedef unsigned char	uint8_t;
typedef unsigned short	uint16_t;
typedef unsigned int	uint32_t;

#define pcm1_start_cnt_phy  0x43c00004  //来帧计数器
#define pcm1_en_phy         0x43c00028  //取值脉冲信号
// devmem 0x43c00018 32 2 逻辑发数据
#define pcm2_start_cnt_phy  0x43c00008
#define pcm2_en_phy         0x43c0002C

#define pcm_reset_phy       0x43c00024  //0 -> 1 -> 0

int axidma_cnt_init();
void *axidma_cnt_mmap(unsigned long addr);
unsigned int get_axidma_cnt(unsigned char dma);
void pcm_reset(void);
void en_pcm(int dma, int en);
void pulse_flag(char channel);
//PCM同步串口
#define pcm_0 0U
#define pcm_1 1U

#define PCM_MEM_BASE			0x43c10000	// PCM PS-PL交互区基地址 //0815 890项目 0x43c00000
#define PCM_MEM_LEN				0x10000 	// PCM PS-PL交互区长度
#define PCM_PORT_NUM 2                      //PCM目前只有一路
#define PCM_BASE_ADDR PCM_MEM_BASE
#define PCM_PORT_ADDR_LEN 0x10000//每个端口占用地址空间
#define PCM_CTRL_REG 0//控制寄存器偏移
#define PCM_TDATA_REG 4 //数据发送寄存器偏移，寄存器16位，只有低8位有效
#define PCM_STAT_REG 8//状态寄存器偏移
#define PCM_TBUFF_USE_COUNT_REG 12//发送FIFO使用字节数，0-1024
#define PCM_RDES_BLOCK_POINT_REG 16//描述符写指针，每个描述符4个字，8个字节，这里的指针是以16bit为单位的
#define PCM_frame_cnt 20           //read 接收帧个数
#define PCM_RDES_BLOCK_RAM_ADDR 0x400//描述符队列起始地址
#define PCM_RBUFF_RAM_ADDR 0x4000//接收数据RAM起始地址偏移，低8位有效
#define PCM_TBUFF_LEN 1024//发送数据FIFO长度
#define PCM_RDES_BLOCK_RAM_LEN 256//描述符队列长度
#define PCM_RBUFF_RAM_LEN 8192//接收数据RAM地址空间，接收数据RAM大小4096B，低8位有效，占用地址空间
#define PCM_CTRL_T_START_BIT 0x0001//控制寄存器，发送开始
#define PCM_CTRL_T_RESET_BIT 0x0002//控制寄存器发送模块复位，写1复位
#define PCM_CTRL_R_RESET_BIT 0x0004//控制寄存器接收模块复位，写1复位
#define PCM_STAT_BUSY_BIT 0x0001//无效
#define PCM_DES_HEAD1_WORD 0//描述符第一个字，目前固定0x5AA5
#define PCM_DES_HEAD2_WORD 1//描述符第二个字，目前固定0xABCD
#define PCM_DES_COR_LEN_WORD 2//描述符第三个字，错误标志和帧长度
#define PCM_DES_COR_BIT 0x8000//描述符第三个字，最高位为错误标识，1有错误
#define PCM_DES_LEN_BIT 0x01FF//描述符第三个字，低9位为帧有效数据长度，0-256
#define PCM_DES_DATA_ADDR_WORD 3//描述符第四个字，数据帧在接收数据RAM的起始地址
#define PCM_BAG_SIZE 1020 //每包长度
#define PCM_RECEIVE_BUFF_SIZE 0x2000 //包个数
#define PCM_ENABLE_VALUE 0x1A

typedef struct PCM_CB
{
    uint32_t Port;			//端口号
    uint32_t Enable;		//控制块是否初始化过
    uint32_t InitOK;		//端口是否初始化完成
	/***************** PCM寄存器begin ***************/
	// 控制
    uint32_t CTAddr;	//控制寄存器地址:     0x000
    // 发送相关
    uint32_t TAddr;		//发送数据寄存器地址: 0x001<<1, [bit7:0]: 为发送的数据
    uint32_t STAddr;	//发送状态寄存器地址: 0x002<<1, [bit1]=1：发送出现帧错误;
                        //                                    =0：发送正常。
						//                              [bit0]=1：busy
						//                                    =0：free
						//注意: 对该寄存器写访问可对该bit清零
    uint32_t TUCAddr;	//发送区占用字节数寄存器地址: 0x003<<1, 总大小1KB
	// 接收相关
    uint32_t DesPAddr;	//描述符指针地址
    uint32_t DesAddr;	//描述符RAM地址
    uint32_t RAddr;		//接收数据RAM地址

    uint32_t Frame_addr  ;//pcm接收帧数量地址
    /***************** PCM寄存器end ***************/

    uint16_t DesPRec;//前一次软件服务完成时描述符指针，其实就是描述符读指针
    uint8_t RBuf[PCM_RECEIVE_BUFF_SIZE][PCM_BAG_SIZE];//接收软件缓冲
    uint32_t RBufWrite;//接收软件缓冲写指针
    uint32_t RBufRead; //接收软件缓冲读指针
    uint32_t RBufLock;
    uint32_t initCnt; //调试用
    //SEM_ID semT;//发送互斥信号量
    //SEM_ID semR;//接收互斥信号量
    //SEM_ID semIntT;//中断信号量 无用
    pthread_t rxThrd;
} PCM_CB;//PCM控制块

void *devm_map(unsigned long addr, int len, int *phandle);
void PCMTest(int num);
uint32_t PCMSend(uint32_t u32Port, uint8_t u8aSData[], uint32_t u32Len);
uint32_t PCMReceive(uint32_t u32Port, uint8_t *DataBuf);
void PCMInit(uint32_t u32Port);
void taskPCMReceive(void);
void *PCMReceiveISR_0(void *arg);
void *PCMReceiveISR_1(void *arg);
void IO_WRITE16(uint32_t addr, uint16_t value);
uint16_t IO_READ16(uint32_t addr);
void print_data(char *data, int len);
void PCMCBCreat(uint32_t u32Port);
void PCM_Test_890();
void PCMPrint(uint32_t u32Port);
uint16_t PCM_frame_count(int port);
void PCM_frame_clear(int port);
void sleep_ms(unsigned int secs);

#endif /* SRC_PCM_PCM_H_ */
